﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Engine.Sgml.Allocation {
    internal sealed class DescendantsIterator : INodeIterator {
        private int rootDepth;
        private SElement root;
        private SElement current;

        public void Reset(SElement element) {
            Guard.ArgumentNotNull(element, "element");
            root = element;
            rootDepth = root.Depth;
            current = root;
            }

        public bool MoveNext() {
            if (current == null)
                return false;
            SElement next = current.FirstNonCommentNode();
            if (next == null) {
                next = current.NextNonCommentNode();
                if (next == null) {
                    current = current.Parent;
                    while (current != null && current.Depth > rootDepth) {
                        next = current.NextNonCommentNode();
                        if (next == null)
                            current = current.Parent;
                        else {
                            current = next;
                            return true;
                            }
                        }
                    current = null;
                    return false;
                    }
                else if (next.Depth == rootDepth) {
                    current = next;
                    return MoveNext();
                    }
                }
            current = next;
            return true;
            }

        public bool MovePrevious() {
            if (current == null)
                return false;
            SElement prev = current.LastNonCommentNode();
            if (prev == null) {
                prev = current.PreviousNonCommentNode();
                if (prev == null) {
                    current = current.Parent;
                    while (current != null && current.Depth > rootDepth) {
                        prev = current.PreviousNonCommentNode();
                        if (prev == null)
                            current = current.Parent;
                        else {
                            current = prev;
                            return true;
                            }
                        }
                    current = null;
                    return false;
                    }
                else if (prev.Depth == rootDepth) {
                    current = prev;
                    return MovePrevious();
                    }
                }
            current = prev;
            return true;
            }

        public SElement Current { get { return current; } }
        }
    }
